package com.evil.common.es.dto.application.order;

import com.evil.common.application.dto.order.OrderPageDataRespDTO;
import com.evil.common.application.enums.order.OrderProcessStatusEnum;
import com.evil.common.es.dto.application.order.data.ESControlDataDTO;
import com.evil.common.es.dto.application.order.node.ESNodeHandlerDTO;
import lombok.Data;
import org.elasticsearch.core.Nullable;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单 请求实体
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Data
@Document(indexName = ESOrderDataDTO.INDEX)
public class ESOrderDataDTO {

    public static final String INDEX = "order_data";
    public static final String COL_AK = "application_key";
    public static final String COL_AI = "application_id";
    public static final String COL_EI = "enterprise_id";
    public static final String COL_OI = "order_id";
    public static final String COL_ID = "_id";
    public static final String COL_OS = "order_sn";
    public static final String COL_PS = "process_status";
    public static final String COL_DATA = "data";
    public static final String COL_DN = "data_nested";
    public static final String COL_CI = "creator_id";
    public static final String COL_MI = "modifier_id";
    public static final String COL_CREATED = "created";
    public static final String COL_UPDATED = "updated";
    public static final String COL_NH = "node_handlers";
    public static final String COL_NHN = "node_handlers_nested";
    /**
     * 应用key
     */
    @Nullable
    @Field(name = COL_AK, type = FieldType.Keyword)
    private String applicationKey;
    /**
     * 应用id
     */
    @Nullable
    @Field(name = COL_AI, type = FieldType.Long)
    private Long applicationId;
    /**
     * 企业id
     */
    @Nullable
    @Field(name = COL_EI, type = FieldType.Long)
    private Long enterpriseId;
    /**
     * 订单id
     */
    @Id
    @Nullable
    private Long orderId;
    /**
     * 订单编号
     */
    @Field(name = COL_OS, type = FieldType.Keyword)
    private String orderSn;
    /**
     * 流程状态(0:草稿箱, 1:流程中, 2:已完成)
     */
    @Field(name = COL_PS, type = FieldType.Long)
    private Integer processStatus;
    /**
     * 数据
     */
    @Valid
    @Field(name = COL_DATA, type = FieldType.Object)
    private List<ESControlDataDTO> data;
    /**
     * 数据（Nested）
     */
    @Valid
    @Field(name = COL_DN, type = FieldType.Nested)
    private List<ESControlDataDTO> dataNested;
    /**
     * 创建人
     */
    @Field(name = COL_CI, type = FieldType.Long)
    private Long creatorId;
    /**
     * 更新人
     */
    @Field(name = COL_MI, type = FieldType.Long)
    private Long modifierId;
    /**
     * 创建时间
     */
    @Field(name = COL_CREATED, type = FieldType.Date)
    private Date created;
    /**
     * 更新时间
     */
    @Field(name = COL_UPDATED, type = FieldType.Date)
    private Date updated;
    /**
     * 节点处理人
     */
    @Field(name = COL_NH, type = FieldType.Object)
    private List<ESNodeHandlerDTO> nodeHandlers;
    /**
     * 节点处理人
     */
    @Field(name = COL_NHN, type = FieldType.Nested)
    private List<ESNodeHandlerDTO> nodeHandlersNested;

    public ESOrderDataDTO() {
        this.processStatus = OrderProcessStatusEnum.DRAFT_BOX.getId();
        this.data = new ArrayList<>();
        this.dataNested = new ArrayList<>();
        this.nodeHandlersNested = new ArrayList<>();
    }

    private void setData(List<ESControlDataDTO> data) {
    }

    public void setData(List<ESControlDataDTO> data, Function<String, Boolean> isTableData) {
        this.data = data;
        this.dataNested = new ArrayList<>();
        data.forEach(d -> {
            this.dataNested.add(d);
            if (isTableData.apply(d.getControlCode())) {
                d.getTableValues().forEach(row -> this.dataNested.addAll(row));
            }
        });
    }

    public void setNodeHandlers(List<ESNodeHandlerDTO> nodeHandlers) {
        this.nodeHandlers = nodeHandlers;
        this.nodeHandlersNested = nodeHandlers;
    }

    public void setNodeHandlersNested(List<ESNodeHandlerDTO> nodeHandlersNested) {
        this.nodeHandlers = nodeHandlersNested;
        this.nodeHandlersNested = nodeHandlersNested;
    }

    public OrderPageDataRespDTO toOrderPageDataRespDTO() {
        OrderPageDataRespDTO orderPageDataRespDTO = new OrderPageDataRespDTO();
        orderPageDataRespDTO.setApplicationKey(this.applicationKey);
        orderPageDataRespDTO.setApplicationId(this.applicationId);
        orderPageDataRespDTO.setEnterpriseId(this.enterpriseId);
        orderPageDataRespDTO.setOrderId(this.orderId);
        orderPageDataRespDTO.setOrderSn(this.orderSn);
        orderPageDataRespDTO.setProcessStatus(this.processStatus);
        orderPageDataRespDTO.setData(this.data.stream().map(ESControlDataDTO::toControlDataDTO).collect(Collectors.toList()));
        orderPageDataRespDTO.setCreatorId(this.creatorId);
        orderPageDataRespDTO.setModifierId(this.modifierId);
        orderPageDataRespDTO.setCreated(this.created);
        orderPageDataRespDTO.setUpdated(this.updated);

        return orderPageDataRespDTO;
    }
}
